﻿using System;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AudioDjStudio;
using AxSLIDERLib;

namespace IntelliTouchMix
{
    public enum PlayerDeck { 
        DECKA,
        DECKB,
        PREVIEW,
        ANALIZE
    }

    public partial class FormMain
    {

        SongInfo[] playerInfo;
        PlayerDeck selectedPlayer = PlayerDeck.DECKA;

        private delegate void SetControlPropertyThreadSafeDelegate(Control control, string propertyName, object propertyValue);

        public void initUserCode()
        {
            int i;
            for (playerInfo = new SongInfo[i = 4]; i > 0; playerInfo[--i] = new SongInfo()) ;

        }

        public void loadUserCode()
        {
            this.audioDjStudio1.BeatsAvailableOffline += new AudioDjStudio.AudioDjStudio.BeatsAvailableOfflineEventHandler(audioDjStudio1_BeatsAvailableOffline);
            this.audioDjStudio1.BeatDetectedRealTime += new AudioDjStudio.AudioDjStudio.BeatDetectedRealTimeEventHandler(audioDjStudio1_BeatDetectedRealTime);
        }

        public void ManageTouchDownOnScroll(Int16 nPlayerIndex, TouchMouseEventArgs e)
        {

            enumPlayerStatus status = audioDjStudio1.GetPlayerStatus(nPlayerIndex);
            if (status == enumPlayerStatus.SOUND_PLAYING)
            {
                audioDjStudio1.PauseSound(nPlayerIndex);
                m_bMustResumeOnMouseUp[nPlayerIndex] = true;
            }
            else
                m_bMustResumeOnMouseUp[nPlayerIndex] = false;

            enumScaleUnits nScaleUnits = audioDjStudio1.ScaleUnits;
            audioDjStudio1.ScaleUnits = enumScaleUnits.SCALE_MILLISECONDS;

            PictureBox pictureBoxWaveformScroll;
            PictureBox pictureBoxWaveformFull;
            if (nPlayerIndex == PLAYER1)
            {
                pictureBoxWaveformScroll = pictureBoxWaveformScroll1;
                pictureBoxWaveformFull = pictureBoxWaveformFull1;
            }
            else
            {
                pictureBoxWaveformScroll = pictureBoxWaveformScroll2;
                pictureBoxWaveformFull = pictureBoxWaveformFull2;
            }

            // determine the position of the click from pixels to ms
            Int32 nViewWidthInPixels = pictureBoxWaveformScroll.Width;
            Int32 nViewWidthInMs = m_nWaveformScrollEndPosInMs[nPlayerIndex] - m_nWaveformScrollStartPosInMs[nPlayerIndex];

            float fPixelDurationInMs = (float)nViewWidthInMs / (float)nViewWidthInPixels;

            m_nPixelPositionOnWaveform[nPlayerIndex] = (int)e.distance;

            int sign = e.senseType == SenseType.POSITIVE ? 1 : -1;

            int soundDuration = audioDjStudio1.GetSoundDuration(nPlayerIndex);
            Int32 advance = (Int32)(Util.snapValue[Util.snapStatus] * playerInfo[nPlayerIndex].mode * sign);
            Console.WriteLine(advance);
            Int32 nPositionToSeekInMs = m_nWaveformScrollStartPosInMs[nPlayerIndex] + advance + 5000;
            Console.WriteLine(nPositionToSeekInMs);
            if (nPositionToSeekInMs < 0)
                nPositionToSeekInMs = 0;
            if (nPositionToSeekInMs <= 0 && e.senseType == SenseType.POSITIVE)
                nPositionToSeekInMs = advance;
            if (nPositionToSeekInMs > soundDuration)
                nPositionToSeekInMs = soundDuration;

            // move the current playback position
            audioDjStudio1.SeekSound(nPlayerIndex, (UInt32)nPositionToSeekInMs);

            // update scrolling waveform
            DrawWaveformScrolling(nPlayerIndex, pictureBoxWaveformScroll);

            // update full waveform
            float fPixelDurationOnFullInMs = soundDuration / pictureBoxWaveformFull.Width;
            m_nCurrentPosInPixels[nPlayerIndex] = (Int32)((float)audioDjStudio1.GetPlaybackTime(nPlayerIndex) / fPixelDurationOnFullInMs);
            DrawWaveformFull(nPlayerIndex, pictureBoxWaveformFull, m_nCurrentPosInPixels[nPlayerIndex]);

            audioDjStudio1.ScaleUnits = nScaleUnits;
        }

        void audioDjStudio1_BeatDetectedRealTime(object sender, BeatDetectedRealTimeEventArgs e)
        {
            Console.WriteLine("BEAT");
        }

        private void ManageTouchOnFull(Int16 nPlayerIndex, TouchMouseEventArgs e)
        {
            enumScaleUnits nScaleUnits = audioDjStudio1.ScaleUnits;
            audioDjStudio1.ScaleUnits = enumScaleUnits.SCALE_MILLISECONDS;

            PictureBox pictureBoxWaveformScroll;
            PictureBox pictureBoxWaveformFull;
            if (nPlayerIndex == PLAYER1)
            {
                pictureBoxWaveformScroll = pictureBoxWaveformScroll1;
                pictureBoxWaveformFull = pictureBoxWaveformFull1;
            }
            else
            {
                pictureBoxWaveformScroll = pictureBoxWaveformScroll2;
                pictureBoxWaveformFull = pictureBoxWaveformFull2;
            }

            // determine the position of the click from pixels to ms
            Int32 nViewWidthInPixels = pictureBoxWaveformScroll.Width;
            Int32 nViewWidthInMs = audioDjStudio1.GetSoundDuration(nPlayerIndex);

            float fPixelDurationInMs = (float)nViewWidthInMs / (float)nViewWidthInPixels;

            Int32 nPixelPositionOnWaveform = (Int32)e.distance;

            Int32 nPositionToSeekInMs = (Int32)((float)nPixelPositionOnWaveform * fPixelDurationInMs);

            // move the current playback position
            audioDjStudio1.SeekSound(nPlayerIndex, (UInt32)nPositionToSeekInMs);

            // update scrolling waveform
            DrawWaveformScrolling(nPlayerIndex, pictureBoxWaveformScroll);

            // update full waveform
            float fPixelDurationOnFullInMs = audioDjStudio1.GetSoundDuration(nPlayerIndex) / pictureBoxWaveformFull.Width;
            m_nCurrentPosInPixels[nPlayerIndex] = (Int32)((float)audioDjStudio1.GetPlaybackTime(nPlayerIndex) / fPixelDurationOnFullInMs);
            DrawWaveformFull(nPlayerIndex, pictureBoxWaveformFull, m_nCurrentPosInPixels[nPlayerIndex]);

            audioDjStudio1.ScaleUnits = nScaleUnits;
        }


        void audioDjStudio1_BeatsAvailableOffline(object sender, BeatsAvailableOfflineEventArgs e)
        {
            audioDjStudio1.BeatsDetectEnableRT(e.nPlayerIndex, true);

            Dictionary<Int32, Int32> listDif = new Dictionary<Int32, Int32>();
            for (int i = 0; i < e.nBeatsDetected; i++)
            {
                Int32 nBeatPos = audioDjStudio1.BeatsDetectGetBeatPos(0, i);
                listDif.Add(nBeatPos,i>0?audioDjStudio1.BeatsDetectGetBeatPos(0, i) - audioDjStudio1.BeatsDetectGetBeatPos(0, i - 1):0);
                //Console.WriteLine(audioDjStudio1.GetFormattedTime(nBeatPos, false, true));
            }
            var mode = listDif.Values.GroupBy(n => n).
                       OrderByDescending(g => g.Count()).
                       Select(g => g.Key).FirstOrDefault();

            audioDjStudio1.SetForwardRewindGranularity(e.nPlayerIndex, mode);

            playerInfo[e.nPlayerIndex].mode = mode;
            playerInfo[e.nPlayerIndex].bpmMode = 60000 / mode;
            playerInfo[e.nPlayerIndex].beatsInfo = listDif;
        }

        public void analizeSong(short player)
        {
            playerInfo[player] = new SongInfo();
            float fBandwidth = 10;
            float fCutoffFreq = 90;
            float fReleaseTime = 20;
            audioDjStudio1.BeatsDetectSetParams(player, fBandwidth, fCutoffFreq, fReleaseTime);
            int m_nSoundDuration = audioDjStudio1.GetSoundDuration(player);
            audioDjStudio1.BeatsDetectSetRange(player, 0, m_nSoundDuration);
            audioDjStudio1.BeatsDetectRequest(player);
        }

        public int playerPlaying()
        {
            if (audioDjStudio1.GetPlayerStatus(PLAYER1) == enumPlayerStatus.SOUND_PLAYING)
                return 1;
            if (audioDjStudio1.GetPlayerStatus(PLAYER2) == enumPlayerStatus.SOUND_PLAYING)
                return 2;
            return 0;
        }

        public AxGSlider getPitchTrackbar()
        {
            switch (playerPlaying())
            {
                case 1: return GSlider_Tempo1;
                case 2: return GSlider_Tempo2;
                default: return null;
            }
        }

        public void playFadeSongs()
        {
            BtnStartFading_Click(new object(), EventArgs.Empty);
        }

        public void loadDeckA()
        {
            BtnLoadDeckA_Click(new object(), EventArgs.Empty);
        }
        public void loadDeckB()
        {
            BtnLoadDeckB_Click(new object(), EventArgs.Empty);
        }


        public static void SetControlPropertyThreadSafe(Control control, string propertyName, object propertyValue)
        {
            if (control.InvokeRequired)
            {
                control.Invoke(new SetControlPropertyThreadSafeDelegate(SetControlPropertyThreadSafe), new object[] { control, propertyName, propertyValue });
            }
            else
            {
                control.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, control, new object[] { propertyValue });
            }
        }




    }
}
